/*********************************************************************************
 *      Copyright:  (C) 2020 Juan
 *                  All rights reserved.
 *
 *       Filename:  server.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(14/07/20)
 *         Author:  wangruijie <1046299465@qq.com>
 *      ChangeLog:  1, Release initial version on "14/07/20 09:05:12"
 *                 
 ********************************************************************************/
#include"cJSON.h"
#include"json_server.h"

int main(int argc, char **argv) 
{
    int                     rv = -1; 
    int                     listen_fd,  client_fd = -1; 
    struct sockaddr_in      serv_addr; 
    struct sockaddr_in      cli_addr;
    socklen_t               cliaddr_len; 
    char                    buf[1024]; 
    int                     opt;
    char                    *progname = NULL;
    int                     LISTEN_PORT;

    struct option            long_options[]=
    {
        {"port", required_argument, NULL, 'p'},
        {"help", no_argument, NULL, 'h'},
        {NULL, 0, NULL, 0}
    };

    progname = basename(argv[0]);

    while((opt = getopt_long(argc,argv,"p:h",long_options,NULL))!=-1)
    {
        switch(opt)
        {
            case 'p':
                LISTEN_PORT = atoi(optarg);
                break;

            case 'h':
                print_usage(progname);
                return EXIT_SUCCESS;

            default:
                break;
        }
    }

    if(!LISTEN_PORT)
    {
        print_usage(argv[0]);
        return 0;
    }

    listen_fd = socket(AF_INET, SOCK_STREAM, 0); 
    if(listen_fd < 0)
    {
         printf("create socket failure: %s\n", strerror(errno)); 
         return -1;
    }
    printf("socket create fd[%d]\n", listen_fd); 

    memset(&serv_addr, 0, sizeof(serv_addr)); 
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(LISTEN_PORT);
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 

    if( bind(listen_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0 ) 
    {
        printf("create socket failure: %s\n", strerror(errno)); 
        return -2;
    }
    printf("socket[%d] bind on port[%d] for all IP address ok\n", listen_fd, LISTEN_PORT); 

    listen(listen_fd, BACKLOG);

    while(1)
    {
        printf("\nStart waiting and accept new client connect...\n", listen_fd);
        client_fd = accept(listen_fd, (struct sockaddr*)&cli_addr, &cliaddr_len); 
        if(client_fd < 0) 
        {
            printf("accept new socket failure: %s\n", strerror(errno)); 
            return -2;
        }
        printf("Accept new client[%s:%d] with fd [%d]\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port), client_fd); 

        memset(buf, 0, sizeof(buf));
        if( (rv=read(client_fd, buf, sizeof(buf))) < 0) 
        {
            printf("Read data from client socket[%d] failure: %s\n", client_fd, strerror(errno)); 
            close(client_fd);
            continue;
        }
        else if( rv == 0 ) 
        {
            printf("client socket[%d] disconnected\n", client_fd); 
            close(client_fd); 
            continue;
        }
        printf("read  data from client[%d] and echo it back:%s\n", client_fd, buf); 

        rv = unpack_json(buf);
        if(rv < 0)
        {
            printf("unpack data failure:%s\n", strerror(errno));
            return -2;
        }

        sleep(1);
        close(client_fd);
    }
    close(listen_fd);

}
